package com.seres.math;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.seres.backend.AnswerDecision;
import com.seres.backend.CorrectiveDecision;
import com.seres.backend.Decision;
import com.seres.data.Index;
import com.seres.data.IndexImpact;
import com.seres.data.Stakeholder;

public class ImpactAnalyzer {
	private List<IndexEthicalStatus> actualIndexEthicalStatus;
	private List<StakeholderEthicalStatus> actualStakeholderEthicalStatus;
	
	private RiskCalculator riskCalculator;
	private TrustCalculator trustCalculator;
	private STICalculator stiCalculator;
	
	private StakeholderImpactCalculator stakeholderImpactCalculator;
	
	private AiEngine aiEngine;
	
	private List<Decision> decisions;
	private List<Stakeholder> stakeholders;
	private List<Index> indices;
	
	public ImpactAnalyzer(List<Stakeholder> stakeholders, List<Index> indices){
		setStakeholders(stakeholders);
		setIndices(indices);
		
		initializeEthicalStatus();
		setDecisions(new ArrayList<Decision>());

		
		setRiskCalculator(new RiskCalculator());
		setTrustCalculator(new TrustCalculator());
		setStiCalculator(new STICalculator());
		setStakeholderImpactCalculator(new StakeholderImpactCalculator());
	}
	private void initializeEthicalStatus(){
//		Stakeholder[] stakeholders = Stakeholder.values();
		
		actualIndexEthicalStatus = new ArrayList<IndexEthicalStatus>();
		actualStakeholderEthicalStatus = new ArrayList<StakeholderEthicalStatus>();
		
//		for(int i = 0; i < stakeholders.length; i++){
//			actualStakeholderEthicalStatus.add(new StakeholderEthicalStatus(stakeholders[i].getInitialStatusValue(), stakeholders[i]));
//		}
		for(int i = 0; i < getStakeholders().size(); i++){
			actualStakeholderEthicalStatus.add(new StakeholderEthicalStatus(getStakeholders().get(i).getInitialStatusValue(), getStakeholders().get(i)));
		}
//		Index[] indices = Index.values();
		
//		for(int i = 0; i < indices.length; i++){
//			actualIndexEthicalStatus.add(new IndexEthicalStatus(indices[i].getInitialStatusValue(), indices[i]));
//		}
		for(int i = 0; i < getIndices().size(); i++){
			actualIndexEthicalStatus.add(new IndexEthicalStatus(getIndices().get(i).getInitialStatusValue(), getIndices().get(i)));
		}
	}
	public void processNewDecision(Decision decision){
		updateEthicalStatus(decision);
		addDecision(decision);
	}
	private void updateEthicalStatus(Decision decision){
		List<IndexImpact> impacts = null;
		
		if(decision.isAnAnswerDecision()){
			AnswerDecision answerDecision = (AnswerDecision) decision;
			actualStakeholderEthicalStatus = getStakeholderImpactCalculator().calcNewStakeholderStatus(actualStakeholderEthicalStatus, answerDecision.getAnswer().getStakeholderImpactsClone());

			impacts = answerDecision.getAnswer().getIndexImpacts();
		}
		else if(decision.isACorrectiveDecision()){
			CorrectiveDecision correctiveDecision = (CorrectiveDecision) decision;
			actualStakeholderEthicalStatus = getStakeholderImpactCalculator().calcNewStakeholderStatus(actualStakeholderEthicalStatus, correctiveDecision.getAce().getStakeholderImpactsClone());
		
			impacts = correctiveDecision.getAce().getIndexImpacts();
		}
		
		
		Iterator<IndexEthicalStatus> it = actualIndexEthicalStatus.iterator();
		List<IndexEthicalStatus> statusToRemove = new ArrayList<IndexEthicalStatus>();
		List<IndexEthicalStatus> statusToAdd = new ArrayList<IndexEthicalStatus>();
		while(it.hasNext()){
			IndexEthicalStatus indexEthicalStatus = it.next();
			
			Iterator<IndexImpact> it2 = impacts.iterator();
			while(it2.hasNext()){
				IndexImpact impact = it2.next();
				
				if(indexEthicalStatus.getIndex().equals(impact.getIndex())){
					if(indexEthicalStatus.getIndex().getName().equals("Risk")){
//						actualIndexEthicalStatus.add(getRiskCalculator().calcNewRiskStatus(indexEthicalStatus, impact));
						statusToAdd.add(getRiskCalculator().calcNewRiskStatus(indexEthicalStatus.getIndex(),indexEthicalStatus, impact));
			
					}
					
				}
				
			}
			
			if(indexEthicalStatus.getIndex().getName().equals("Trust")){
//				actualIndexEthicalStatus.add(getTrustCalculator().calcNewTrustStatus(actualStakeholderEthicalStatus));
//				System.out.println("*** impact analyzer ***");
				
				statusToAdd.add(getTrustCalculator().calcNewTrustStatus(indexEthicalStatus.getIndex(),actualStakeholderEthicalStatus,getStakeholders().get(0).getMinimumStatusValue(),getStakeholders().get(0).getMaximumStatusValue(),getStakeholders()));
			}
			else if(indexEthicalStatus.getIndex().getName().equals("Short Term Impact")){
//				actualIndexEthicalStatus.add(getStiCalculator().calcNewSTIStatus(actualStakeholderEthicalStatus));
				statusToAdd.add(getStiCalculator().calcNewSTIStatus(indexEthicalStatus.getIndex(),actualStakeholderEthicalStatus,getStakeholders().get(0).getMinimumStatusValue(),getStakeholders().get(0).getMaximumStatusValue(),getStakeholders()));
			}
			

//			actualIndexEthicalStatus.remove(indexEthicalStatus);
			statusToRemove.add(indexEthicalStatus);
		}
		actualIndexEthicalStatus.removeAll(statusToRemove);
		actualIndexEthicalStatus.addAll(statusToAdd);

	}
	public boolean hasStakeholderBelowStatusThreshold(){
		for(StakeholderEthicalStatus status : getActualStakeholderEthicalStatus()){
			if(status.getValue() < status.getStakeholder().getThresholdStatusValue()){
				return true;
			}
		}
		return false;
	}
	public Stakeholder getStakeholderWithLowestStatusBelowThreshold(){
		StakeholderEthicalStatus lowestStatus = null;
		for(StakeholderEthicalStatus status : getActualStakeholderEthicalStatus()){
			if(status.getValue() < status.getStakeholder().getThresholdStatusValue()){
				if(lowestStatus != null){
					if(status.getValue() < lowestStatus.getValue()){
						lowestStatus = status;
					}		
				}
				else{
					lowestStatus = status;
				}
			}
		}
		if(lowestStatus != null){
			return lowestStatus.getStakeholder();
		}
		else{
			return null;
		}

	}
	public boolean isRiskBelowThreshold(){
		for(IndexEthicalStatus status : getActualIndexEthicalStatus()){
			if(status.getIndex().getName().equals("Risk")){
				return status.getValue() < status.getIndex().getThresholdStatusValue();
			}
		}
		return false;
	}
	private void addDecision(Decision decision){
		decisions.add(decision);
	}
	public List<Decision> getDecisions() {
		return decisions;
	}
	public Decision getLastDecision(){
		if(getDecisions().size() > 0){
			return getDecisions().get(getDecisions().size() - 1);
		}
		else{
			return null;
		}
	}
	private void setDecisions(List<Decision> decisions) {
		this.decisions = decisions;
	}
	public RiskCalculator getRiskCalculator() {
		return riskCalculator;
	}
	private void setRiskCalculator(RiskCalculator riskCalculator) {
		this.riskCalculator = riskCalculator;
	}
	public TrustCalculator getTrustCalculator() {
		return trustCalculator;
	}
	private void setTrustCalculator(TrustCalculator trustCalculator) {
		this.trustCalculator = trustCalculator;
	}
	public STICalculator getStiCalculator() {
		return stiCalculator;
	}
	private void setStiCalculator(STICalculator stiCalculator) {
		this.stiCalculator = stiCalculator;
	}
	public StakeholderImpactCalculator getStakeholderImpactCalculator() {
		return stakeholderImpactCalculator;
	}
	private void setStakeholderImpactCalculator(
			StakeholderImpactCalculator stakeholderImpactCalculator) {
		this.stakeholderImpactCalculator = stakeholderImpactCalculator;
	}
	public List<IndexEthicalStatus> getActualIndexEthicalStatus(){
		if(actualIndexEthicalStatus instanceof ArrayList){
			ArrayList<IndexEthicalStatus> actStatus = (ArrayList<IndexEthicalStatus>) actualIndexEthicalStatus;
			return (List<IndexEthicalStatus>) actStatus.clone();
		}
		else{
			return null;
		}
	}
	public List<StakeholderEthicalStatus> getActualStakeholderEthicalStatus(){
		if(actualStakeholderEthicalStatus instanceof ArrayList){
			ArrayList<StakeholderEthicalStatus> actStatus = (ArrayList<StakeholderEthicalStatus>) actualStakeholderEthicalStatus;
			return (List<StakeholderEthicalStatus>) actStatus.clone();
		}
		else{
			return null;
		}
	}
	public List<Stakeholder> getStakeholders() {
		return stakeholders;
	}
	private void setStakeholders(List<Stakeholder> stakeholders) {
		this.stakeholders = stakeholders;
	}
	public List<Index> getIndices() {
		return indices;
	}
	private void setIndices(List<Index> indices) {
		this.indices = indices;
	}

}
